package com.winsdom.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.winsdom.context.BaseContext;
import com.winsdom.dto.CategoryTreeNodes;
import com.winsdom.dto.OrganizationMegAddDTO;
import com.winsdom.dto.OrganizationMegDTO;
import com.winsdom.entity.*;
import com.winsdom.exception.BaseException;
import com.winsdom.exception.BusinessException;
import com.winsdom.mapper.*;
import com.winsdom.service.ICategoryService;
import com.winsdom.service.IOrganizationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.winsdom.vo.OrganizationMegVO;
import com.winsdom.vo.UserAndOrgPageVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static com.winsdom.enums.RedisKey.ORGANIZATION_TREE;
import static com.winsdom.enums.RedisKey.ORGANIZATION_USERS;
/**
 * <p>
 * 组织信息表 服务实现类
 * </p>
 *
 * @author 
 * @since 2025-05-12
 */
@Slf4j
@Service
public class OrganizationServiceImpl extends ServiceImpl<OrganizationMapper, Organization> implements IOrganizationService {
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private ICategoryService iCategoryService;
    @Autowired
    private OrganizationMapper organizationMapper;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public List<CategoryTreeNodes> getOrganizationTree() {
        //获取当前账号信息
        Long userId = Long.valueOf(BaseContext.getCurrentId());
        if (userId == null) {
            throw new BaseException("该账号异常");
        }
        log.info("用户id：{}",userId);
        Long categoryId = Long.valueOf(BaseContext.getCategoryId());
        if (categoryId == null) {
            throw new BaseException("该账号异常");
        }
        log.info("用户组织id：{}",categoryId);
        String cacheKey = ORGANIZATION_TREE.getValue()+userId;
        List<CategoryTreeNodes> categoryTreeNodes = null;
        try {
            //从 Redis 获取缓存数据
            categoryTreeNodes = (List<CategoryTreeNodes>) redisTemplate.opsForValue().get(cacheKey);
        } catch (Exception e) {
            log.error("从Redis获取组织树数据失败: {}", e.getMessage(), e);
        }

        if (categoryTreeNodes == null) {
            try {
                // 查询数据库
                categoryTreeNodes = categoryMapper.getCategoryTreeNodesConcludeRoot(categoryId);
                if (categoryTreeNodes != null) {
                    //将查询结果存入Redis缓存
                    redisTemplate.opsForValue().set(cacheKey, categoryTreeNodes, 1, TimeUnit.HOURS);
                }
            } catch (Exception e) {
                log.error("查询组织树数据失败: {}", e.getMessage(), e);
                // 数据库查询失败时，返回错误响应
                return null;
            }
        }
        return categoryTreeNodes;
    }

    @Override
    public OrganizationMegVO getOrganizationMsg(Long categoryId) {
        if (categoryId == null || categoryId <= 0) {
            throw new BusinessException("没有该组织哟！", HttpStatus.BAD_REQUEST);
        }
        OrganizationMegVO organizationMegVO = categoryMapper.getOrganizationMsg(categoryId);
        if (organizationMegVO == null) {
            throw new BusinessException("未找到组织信息！", HttpStatus.NOT_FOUND);
        }
        String superiorOrganizationName = categoryMapper.getSuperiorOrganizationName(categoryId);
        if (superiorOrganizationName == null) {
            superiorOrganizationName = "无上级组织";
        }
        organizationMegVO.setSuperiorOrganizationName(superiorOrganizationName);
        return organizationMegVO;

    }

    @Override
    public Page<UserAndOrgPageVo> getUserMsg(Long categoryId, Long pageNum, Long pageSize) {
        String cacheKey = ORGANIZATION_USERS.getValue() + categoryId + ":" + pageNum + ":" + pageSize;
        Page<UserAndOrgPageVo> userMsg = null;

        try {
            // 尝试从 Redis 获取缓存数据
            userMsg = (Page<UserAndOrgPageVo>) redisTemplate.opsForValue().get(cacheKey);
        } catch (Exception e) {
            log.error("从 Redis 获取用户信息分页数据失败: {}", e.getMessage(), e);
        }

        if (userMsg == null) {
            try {
                userMsg = queryUserMsgFromDatabase(categoryId, pageNum, pageSize);
                if (userMsg != null) {
                    redisTemplate.opsForValue().set(cacheKey, userMsg, 1, TimeUnit.HOURS);
                }
            } catch (Exception e) {
                log.error("查询用户信息分页数据失败: {}", e.getMessage(), e);
                throw new BusinessException("查询用户信息分页数据失败", HttpStatus.INTERNAL_SERVER_ERROR);
            }
        }

        return userMsg;
    }

    private Page<UserAndOrgPageVo> queryUserMsgFromDatabase(Long categoryId, Long pageNum, Long pageSize) {
        Page<UserAndOrgPageVo> userPage = new Page<>(pageNum, pageSize);
        List<Long> leafIds = categoryMapper.getAllLeaf(categoryId);

        if (leafIds.isEmpty()) {
            return new Page<>();
        }

        userPage = categoryMapper.getUserPage(userPage, leafIds);

        for (UserAndOrgPageVo user : userPage.getRecords()) {
            if (user != null) {
                List<String> roleNames = getRoleNamesByUserId(user.getId());
                user.setRoleNames(roleNames);
            }
        }

        return userPage;
    }

    private List<String> getRoleNamesByUserId(Long userId) {
        LambdaQueryWrapper<SysUserRole> roleWrapper = new LambdaQueryWrapper<>();
        roleWrapper.eq(SysUserRole::getUserId, userId);
        List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectList(roleWrapper);
        List<Long> roleIds = sysUserRoles.stream()
                .map(SysUserRole::getRoleId)
                .collect(Collectors.toList());

        if (roleIds.isEmpty()) {
            return new ArrayList<>();
        }

        LambdaQueryWrapper<SysRole> roleNameWrapper = new LambdaQueryWrapper<>();
        roleNameWrapper.in(SysRole::getId, roleIds);
        List<SysRole> sysRoles = sysRoleMapper.selectList(roleNameWrapper);
        return sysRoles.stream()
                .map(SysRole::getRoleName)
                .collect(Collectors.toList());
    }
//    @Override
//    public Page<UserAndOrgPageVo> getUserMsg(Long categoryId, Long pageNum, Long pageSize) {
//        String cacheKey = "organization:users:" + categoryId + ":" + pageNum + ":" + pageSize;
//        Page<UserAndOrgPageVo> userMsg = (Page<UserAndOrgPageVo>) redisTemplate.opsForValue().get(cacheKey);
//        // 初始化分页对象
//        Page<UserAndOrgPageVo> page = new Page<>(pageNum, pageSize);
//        if (userMsg == null) {
//            // 获取所有叶子节点ID（包括根节点）
//            List<Long> leafIds = categoryMapper.getAllLeaf(categoryId);
//
//            // 如果没有叶子节点，直接返回空分页结果
//            if (leafIds.isEmpty()) {
//                return new Page<>();
//            }
//
//            // 查询用户分页数据
//            Page<UserAndOrgPageVo> userPage = new Page<>(pageNum, pageSize);
//            userPage = categoryMapper.getUserPage(userPage, leafIds);
//
//            // 获取角色信息并填充
//            for (UserAndOrgPageVo user : userPage.getRecords()) {
//                if (user != null) {
//                    // 获取角色ID列表
//                    LambdaQueryWrapper<SysUserRole> roleWrapper = new LambdaQueryWrapper<>();
//                    roleWrapper.eq(SysUserRole::getUserId, user.getId());
//                    List<SysUserRole> sysUserRoles = sysUserRoleMapper.selectList(roleWrapper);
//                    List<Long> roleIds = sysUserRoles.stream()
//                            .map(SysUserRole::getRoleId)
//                            .collect(Collectors.toList());
//                    // 获取角色名称
//                    LambdaQueryWrapper<SysRole> roleNameWrapper = new LambdaQueryWrapper<>();
//                    roleNameWrapper.in(SysRole::getId, roleIds);
//                    List<SysRole> sysRoles = sysRoleMapper.selectList(roleNameWrapper);
//                    List<String> roleNames = sysRoles.stream()
//                            .map(SysRole::getRoleName)
//                            .collect(Collectors.toList());
//                    user.setRoleNames(roleNames);
//                }
//            }
//
//            // 设置分页信息
//            page.setRecords(userPage.getRecords());
//            page.setTotal(userPage.getTotal());
//            page.setCurrent(userPage.getCurrent());
//            userMsg=page;
//            if (userMsg != null) {
//                redisTemplate.opsForValue().set(cacheKey, userMsg, 3600, TimeUnit.SECONDS);
//            }
//        }
//        return userMsg;
//    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void insertOrg(OrganizationMegAddDTO organizationMegDTO, Long userCategoryId) {
        //验证组织名
        checkOrganizationName(organizationMegDTO.getOrganizationName());
        //验证地址
        checkAddress(organizationMegDTO.getAddress());
        //验证银行账户
        checkBankAccount(organizationMegDTO.getBankAccount());
        //验证开户银行
        checkOpeningBank(organizationMegDTO.getOpeningBank());
        //验证统一社会信用码
        checkSocietyCode(organizationMegDTO.getSocietyCode());
        //验证电话
        checkPhone(organizationMegDTO.getPhone());
        //验证上级组织
        checkParentId(organizationMegDTO.getParentId());
        //插入分类表
        Category category = new Category();
        category.setName(organizationMegDTO.getOrganizationName());
        category.setParentId(organizationMegDTO.getParentId());
        category.setType(1);
        category.setStatus(1);
        iCategoryService.save(category);
        //拼接详细地址
        componentAddress(organizationMegDTO);
        //插入组织表
        Organization organization = new Organization();
        BeanUtils.copyProperties(organizationMegDTO,organization);
        organization.setCategoryId(category.getId());

        organizationMapper.insert(organization);

        clearOrganizationCache(userCategoryId);
    }

    @Override
    public void updateOrg(OrganizationMegDTO organizationMegDTO) {
        LambdaQueryWrapper<Organization> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(Organization::getCategoryId, organizationMegDTO.getCategoryId());
        Organization existingOrganization = organizationMapper.selectOne(queryWrapper);
        if (existingOrganization == null) {
            throw new BusinessException("组织信息不存在", HttpStatus.BAD_REQUEST);
        }
        //验证地址
        checkAddress(organizationMegDTO.getAddress());
        //验证银行账户
        checkBankAccount(organizationMegDTO.getBankAccount());
        //验证开户银行
        checkOpeningBank(organizationMegDTO.getOpeningBank());
        //验证统一社会信用码
        if (!organizationMegDTO.getSocietyCode().equals(existingOrganization.getSocietyCode())) {
            checkSocietyCode(organizationMegDTO.getSocietyCode());
        }
        //验证电话
        checkPhone(organizationMegDTO.getPhone());

        //拼接详细地址
        componentAddress(organizationMegDTO);

        Organization organization = new Organization();
        BeanUtils.copyProperties(organizationMegDTO, organization);
        organization.setCategoryId(organizationMegDTO.getCategoryId());

        // 修改组织信息
        LambdaUpdateWrapper<Organization> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Organization::getCategoryId, organizationMegDTO.getCategoryId());
        organizationMapper.update(organization, updateWrapper);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteOrg(Long categoryId,Long userCategoryId) {
        LambdaQueryWrapper<Category> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        categoryLambdaQueryWrapper.eq(Category::getId,categoryId);
        Category category = iCategoryService.getOne(categoryLambdaQueryWrapper);
        if(category.getParentId()==0){
            throw new BusinessException("根节点不能删除", HttpStatus.BAD_REQUEST);
        }
        // 获取所有叶子节点ID
        List<Long> leafIds = categoryMapper.getAllLeaf2(categoryId);
        if(!leafIds.isEmpty()){
            throw new BusinessException("该组织下有关联项目，不能删除", HttpStatus.BAD_REQUEST);
        }
        //获取该节点下所有成员
        LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysUserLambdaQueryWrapper.eq(SysUser::getCategoryId,categoryId);
        List<SysUser> sysUsers = sysUserMapper.selectList(sysUserLambdaQueryWrapper);
        if(!sysUsers.isEmpty()){
            throw new BusinessException("该组织下有关联员工，不能删除", HttpStatus.BAD_REQUEST);
        }

        // 删除组织表
        LambdaUpdateWrapper<Organization> deleteWrapper = new LambdaUpdateWrapper<>();
        deleteWrapper.eq(Organization::getCategoryId,categoryId);
        int rowsAffectedOrg = organizationMapper.delete(deleteWrapper);
        if (rowsAffectedOrg <= 0) {
            throw new BusinessException("删除组织数据失败", HttpStatus.INTERNAL_SERVER_ERROR);
        }
        // 删除类别表
        LambdaUpdateWrapper<Category> deleteWrapper2 = new LambdaUpdateWrapper<>();
        deleteWrapper2.eq(Category::getId,categoryId);
        int rowsAffectedCategory = categoryMapper.delete(deleteWrapper2);
        if (rowsAffectedCategory <= 0) {
            throw new BusinessException("删除组织类别数据失败", HttpStatus.INTERNAL_SERVER_ERROR);
        }

        clearOrganizationCache(userCategoryId);
    }

    private void componentAddress(OrganizationMegAddDTO organizationMegDTO) {
        String area = String.valueOf(organizationMegDTO.getArea());
        String[] split = area.replaceAll("[\\[\\]\" ]", "").split(",");
        StringBuilder stringBuilder = new StringBuilder();
        for (String s:split){
            stringBuilder.append(s);
        }
        StringBuilder address = stringBuilder.append(organizationMegDTO.getAddress());
        organizationMegDTO.setAddress(String.valueOf(address));
    }
    private void componentAddress(OrganizationMegDTO organizationMegDTO) {
        String area = String.valueOf(organizationMegDTO.getArea());
        String[] split = area.replaceAll("[\\[\\]\" ]", "").split(",");
        StringBuilder stringBuilder = new StringBuilder();
        for (String s:split){
            stringBuilder.append(s);
        }
        StringBuilder address = stringBuilder.append(organizationMegDTO.getAddress());
        organizationMegDTO.setAddress(String.valueOf(address));
    }
    // 验证企业名称
    private void checkOrganizationName(String organizationName) {
        if (organizationName == null || organizationName.length() < 10 || organizationName.length() > 50) {
            throw new BusinessException("企业名称必须在10到50个字符之间", HttpStatus.BAD_REQUEST);
        }
        // 检查企业名称是否已存在
        boolean exists = iCategoryService.getOne(
                new LambdaQueryWrapper<Category>()
                        .eq(Category::getName, organizationName)
                        .eq(Category::getType, 1)
        ) != null;
        if (exists) {
            throw new BusinessException("组织名称已存在", HttpStatus.BAD_REQUEST);
        }
    }

    // 验证上级组织
    private void checkParentId(Long parentId) {
        if (parentId == null || parentId < 0) {
            throw new BusinessException("上级组织ID无效", HttpStatus.BAD_REQUEST);
        }
    }

    // 验证统一社会信用码
    private void checkSocietyCode(String societyCode) {
        if (societyCode == null || societyCode.length() != 18) {
            throw new BusinessException("统一社会信用码必须为18位", HttpStatus.BAD_REQUEST);
        }
        // 检查是否为数字或字母
        if (!Pattern.matches("^[A-Za-z0-9]+$", societyCode)) {
            throw new BusinessException("统一社会信用码只能包含数字和字母", HttpStatus.BAD_REQUEST);
        }
        // 检查统一社会信用码是否已存在
        boolean exists = organizationMapper.selectOne(
                new LambdaQueryWrapper<Organization>()
                        .eq(Organization::getSocietyCode, societyCode)
        ) != null;
        if (exists) {
            throw new BusinessException("统一社会信用码已存在", HttpStatus.BAD_REQUEST);
        }

    }

    // 验证开户银行
    private void checkOpeningBank(String openingBank) {
        if (openingBank == null || openingBank.length() < 10 || openingBank.length() > 50) {
            throw new BusinessException("开户银行名称必须在10到50个字符之间", HttpStatus.BAD_REQUEST);
        }
    }

    // 验证银行账号
    private void checkBankAccount(String bankAccount) {
        if (bankAccount == null || bankAccount.length() < 12 || bankAccount.length() > 25) {
            throw new BusinessException("银行账号必须在12到25位之间", HttpStatus.BAD_REQUEST);
        }
        // 检查是否为数字
        if (!Pattern.matches("^[0-9]+$", bankAccount)) {
            throw new BusinessException("银行账号必须为数字", HttpStatus.BAD_REQUEST);
        }
    }

    // 验证注册地址
    private void checkAddress(String address) {
        if (address == null || address.length() > 40) {
            throw new BusinessException("详细地址不能超过40个字符", HttpStatus.BAD_REQUEST);
        }
    }

    // 验证企业电话
    private void checkPhone(String phone) {
        String[] split = phone.replaceAll("[\\[\\]\" ]", "").split(",");
        List<String> phoneList = Arrays.asList(split);

        if (phoneList != null) {
            if (phoneList.size() > 3) {
                throw new BusinessException("最多只能添加3个联系电话", HttpStatus.BAD_REQUEST);
            }
            for (String p : phoneList) {
                if (p == null || p.length() < 8 || p.length() > 15) {
                    throw new BusinessException("电话号码长度必须在8到15位之间", HttpStatus.BAD_REQUEST);
                }
                // 验证电话号码是否为数字
                if (!Pattern.matches("^[0-9]+$", p)) {
                    throw new BusinessException("电话号码必须为数字", HttpStatus.BAD_REQUEST);
                }
            }
        }
    }
    /**
     * 清除组织相关的缓存
     */
    private void clearOrganizationCache(Long categoryId) {
        String cacheKey = ORGANIZATION_TREE.getValue()+categoryId;
        try {
            redisTemplate.delete(cacheKey);
        } catch (Exception e) {
            log.error("清除组织缓存失败: {}", e.getMessage(), e);
        }
    }

}

